package com.jiangruan.project.address;

import com.jiangruan.project.utils.Base58;
import com.jiangruan.project.utils.Hash;
import org.bouncycastle.jcajce.provider.symmetric.ARC4;

import java.security.*;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.ECPoint;
import java.util.Arrays;

/**
 * @author:liangdu
 * @email:1487001474@qq.com
 * @desc:
 * @datetime: 2021/12/20 10:47
 */
public class Address {
    public KeyPair generatekey() {
        try {
            KeyPairGenerator generator = KeyPairGenerator.getInstance("EC");
            //p256算法
            ECGenParameterSpec spec = new ECGenParameterSpec("secp256k1");
            generator.initialize(spec);
            return generator.generateKeyPair();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 根据提供的密钥对数据，推导生成一个
     *
     * @param keyPair
     * @return
     */
    public String newAddress(KeyPair keyPair) {
        if (keyPair == null) {
            return null;
        }
        ECPublicKey aPublic = (ECPublicKey) keyPair.getPublic();
        ECPoint ecPoint = aPublic.getW();
        byte[] xBytes = ecPoint.getAffineX().toByteArray();
        byte[] yBytes = ecPoint.getAffineY().toByteArray();
//        System.out.println(xBytes.length);
////        System.out.println(yBytes.length);//32

        byte[] pubkey = toUncompressPubkey(xBytes, yBytes);

        System.out.println(pubkey.length);

        byte[] sha256 = Hash.SHA256(pubkey);
        //公钥hash
        byte[] pubHash = Hash.RIPEMD160(sha256);


        //添加前缀
        byte[] version = new byte[1];
        version[0] = 0x00;
        byte[] ver_pubhash = new byte[version.length + pubHash.length];
        System.arraycopy(version, 0, ver_pubhash, 0, version.length);
        System.arraycopy(pubHash, 0, ver_pubhash, 1, pubHash.length);


        //双哈希，取校验位
        byte[] hash1 = Hash.SHA256(ver_pubhash);
        byte[] hash2 = Hash.SHA256(hash1);
        byte[] check = new byte[4];
        System.arraycopy(hash2, 0, check, 0, 4);


        byte[] ver_pubhash_check = new byte[ver_pubhash.length + check.length];
        System.arraycopy(ver_pubhash, 0, ver_pubhash_check, 0, ver_pubhash.length);
        System.arraycopy(check, 0, ver_pubhash_check, ver_pubhash.length, check.length);

        //base58编码


        return Base58.encode(ver_pubhash_check);
    }

    public boolean validateAddr(String addr) {
        if ("".equals(addr) || addr == null) {
            return false;
        }
        byte[] ver_pubhash_check = Base58.decode(addr);
        if (ver_pubhash_check.length < 4) {
            return false;
        }
        byte[] check = new byte[4];
        System.arraycopy(ver_pubhash_check, ver_pubhash_check.length - 4, check, 0, 4);

        byte[] ver_pubhash = new byte[ver_pubhash_check.length - 4];
        System.arraycopy(ver_pubhash_check, 0, ver_pubhash, 0, ver_pubhash.length);

        //双hash取前四个字节
        byte[] hash1 = Hash.SHA256(ver_pubhash);
        byte[] hash2 = Hash.SHA256(hash1);
        if (hash2 == null) {
            return false;
        }
        byte[] check_sum = new byte[4];
        System.arraycopy(hash2, 0, check_sum, 0, check_sum.length);

        //比较两个字节数组是否相等
        return Arrays.equals(check, check_sum);


    }


    //该方法根据x坐标和y坐标数据，用于拼接
    private static byte[] toUncompressPubkey(byte[] x, byte[] y) {
        byte[] publicKey = new byte[65];
        publicKey[0] = 04;
        if (x.length == 32) {
            //将x坐标全部拷贝到创建的原始格式公钥中去
            System.arraycopy(x, 0, publicKey, 1, x.length);
        } else if (x.length > 32) {
            System.arraycopy(x, 1, publicKey, 1, 32);
        }
        if (y.length == 32) {
            System.arraycopy(y, 0, publicKey, 33, y.length);
        } else if (y.length > 32) {
            System.arraycopy(y, 1, publicKey, 33, 32);
        }
        return publicKey;
    }

////测试
//    public static void main(String[] args) {
//        Address address = new Address();
//        KeyPair generatekey = address.generatekey();
//     String addre  =   address.newAddress(generatekey);
//    boolean isValid =  address.validateAddr(addre);
//        System.out.println(isValid);
//
//    }
}
